<template>


</template>

<script setup name="Home">
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import Stats from 'three/examples/jsm/libs/stats.module.js'
import { CSS3DRenderer,CSS3DObject} from 'three/addons/renderers/CSS3DRenderer.js';
import { CSS2DRenderer,CSS2DObject} from 'three/addons/renderers/CSS2DRenderer.js';
//把原生的dom转出2d物体
//与3d使用基本一致
// 区别1,2d物体智能使用three.js的position位移属性
let scene,camera,renderer,controls,stats,mesh,helper,cssRenderer,css2DRenderer;
 scene = new THREE.Scene();

//透视摄像机（模拟人眼）
 camera = new THREE.PerspectiveCamera(75,
    window.innerWidth / window.innerHeight,
    0.1, 1000);

 renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

//渲染器开启阴影支持
renderer.shadowMap.enabled=true;
document.body.appendChild(renderer.domElement);

camera.position.z = 5;

//初始化css3D渲染器 就是设置了css3d样式的div标签
cssRenderer=new CSS3DRenderer();
cssRenderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(cssRenderer.domElement);


css2DRenderer=new CSS2DRenderer();
css2DRenderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(css2DRenderer.domElement);

//div与canvas并列了 下面设置将css3d覆盖在renderer上面
css2DRenderer.domElement.style.position='fixed';
css2DRenderer.domElement.style.top='0';
css2DRenderer.domElement.style.left='0';
//此时轨道控制 无法移动 div挡住了canvas，轨道控制器是监听canvas标签上的鼠标交互
css2DRenderer.domElement.style.pointerEvents='none'//不触发鼠标交互


//div与canvas并列了 下面设置将css3d覆盖在renderer上面
cssRenderer.domElement.style.position='fixed';
cssRenderer.domElement.style.top='0';
cssRenderer.domElement.style.left='0';
//此时轨道控制 无法移动 div挡住了canvas，轨道控制器是监听canvas标签上的鼠标交互
cssRenderer.domElement.style.pointerEvents='none'//不触发鼠标交互


//轨道控制器改变摄像机的位置
function createOrbitControls() {
    //参数1 控制的摄像机
    //参数2 鼠标交互的标签(监听canvas画布鼠标滑动交互)
    controls = new OrbitControls(camera, renderer.domElement);
    //controls = new OrbitControls(camera, cssRenderer.domElement);
}




function resize() {
    //监听窗口尺寸的改变
    window.addEventListener('resize', () => {
        //设置画布的宽高
        renderer.setSize(window.innerWidth, window.innerHeight);
        //更新摄像机矩阵空间  让摄像机重新计算每个像素点位置
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        //css3d渲染器适配
        cssRenderer.setSize(window.innerWidth, window.innerHeight);

    })
}

//性能监控
function createStats(){
    stats = new Stats();
    stats.setMode(0);//0 每帧刷新帧数  1每帧用时 2 内存占用
    stats.domElement.style.position = 'absolute'
    stats.domElement.style.left = '0px'
    stats.domElement.style.top = '0px'
    document.body.appendChild(stats.domElement)
}


//使用球体+标准网络材质 来对灯光做出反应
function createQiu(){
    //如果没有光 那么就是黑色
    const geometry = new THREE.SphereGeometry( 2, 32, 16 );
    const material = new THREE.MeshStandardMaterial({color:"red"})
    mesh = new THREE.Mesh( geometry, material );
 
    scene.add( mesh );
}



function createFloor(){
    const geometry = new THREE.PlaneGeometry( 10,10 );
    //第二额参数 渲染2个面   roughness:0.5 粗糙度  0反光  粗糙的话就反光  const material = new THREE.MeshBasicMaterial({color:0xffff00,side:THREE.DoubleSide})
    const material = new THREE.MeshStandardMaterial({color:0xffffff,side:THREE.DoubleSide,roughness:0.5})
    const plane = new THREE.Mesh( geometry, material );
   
    scene.add( plane );
    plane.rotation.x= -Math.PI / 2;
    plane.position.y=-1;

}





//灯光阴影
//渲染器计算阴影
//灯光产生阴影
//物体产生阴影
//地面接收阴影计算
function createShadow(){
    //平行光 光的颜色 强度
    const directionLight=new THREE.DirectionalLight(0xffffff,5);
    directionLight.position.set(3,3,3)
    
    scene.add( directionLight );
 
    //光源辅助对象 用线段模拟光源位置 第二个参数是辅助线的宽高
     helper=new THREE.DirectionalLightHelper(directionLight,3)
    scene.add( helper );
}

function create3DDom(){
    const dom = document.createElement('span');
    dom.innerHTML='球体';
    dom.style.color='red';
    //注意此dom不必要自己手动添加到body,而是依赖于转换后3D物体渲染（会被three）加入到div容器中
    const dom3d=new CSS3DObject(dom);
    //虽然没拥有材质和集合图形属性 但是可以根据three中的position，rotation。scale

    dom3d.position.set(0,2,0);
      //原生dom在转换3d物体是 （px大小用作three中单位 默认16个单位 所以这里缩放16分之一）
    dom3d.scale.set(1/16,1/16,1/16)
    dom.addEventListener('click',()=>{
        alert("11")
    })
  
    scene.add(dom3d)
}

function create2DDom(){
    const dom = document.createElement('span');
    dom.innerHTML='球体';
    dom.style.color='red';
    //注意此dom不必要自己手动添加到body,而是依赖于转换后3D物体渲染（会被three）加入到div容器中
    const dom2d=new CSS2DObject(dom);
    //只有three的position属性 始终面向自己 
    //不跟着缩放放大

    dom2d.position.set(1,2,0);
      //原生dom在转换3d物体是 （px大小用作three中单位 默认16个单位 所以这里缩放16分之一）
    //   dom2d.scale.set(1/16,1/16,1/16)
  
    scene.add(dom2d)
}

//精灵物体 始终面向摄像机 能被其他物体遮挡 缩放
function createSprite(){

    const map =new THREE.TextureLoader().load('src/assets/avatar.png')
    //颜色贴图
    const material = new THREE.SpriteMaterial({map:map})

    const sprite = new THREE.Sprite(material);
    sprite.position.set(3,-0.5,3)
    scene.add(sprite);
}
function animate() {
    //根据浏览器刷新帧率 默认1s60次 不断递归调用此渲染函数 为了让render渲染最新的画面
    requestAnimationFrame(animate);
    controls.update();

    stats.update()
 
    //用css3d渲染器把当下世界和摄像机传入渲染
    
    renderer.render(scene, camera)
    cssRenderer.render(scene,camera)
    css2DRenderer.render(scene,camera)
}
resize();
createStats();

createOrbitControls();

createQiu();

createFloor();

createShadow()
// create3DDom();
// create2DDom();
createSprite();
animate();

</script>
<style scoped></style>